package menu

import (
	"fmt"
	"github.com/goravel/framework/facades"
	"github.com/spf13/viper"
	"goravel/app/models"
	"sort"
)

type MenuService struct{}

func NewMenuService() *MenuService {
	return &MenuService{}
}

func (m *MenuService) InitMenu() error {
	return m.ParseFile()
}

func (m *MenuService) ParseFile() error {
	//先trancatemenus表
	v1 := viper.New()
	v1.SetConfigFile("./config.json")
	v1.SetConfigName("config")
	v1.SetConfigType("json")
	v1.AddConfigPath("app/services/menu") // 第一个搜索路径
	if err := v1.ReadInConfig(); err != nil {
		fmt.Printf("Error reading config file: %s\n", err)
		return err
	}
	type MenuData struct {
		Data []models.Menu `json:"data"`
	}
	var menuData MenuData
	if err := v1.Unmarshal(&menuData); err != nil {
		fmt.Println("Error unmarshalling JSON:", err)
		return err
	}
	query := facades.Orm().Query()
	truncateSql := "truncate table menus"
	query.Exec(truncateSql)
	return m.RecursionCrt(menuData.Data)
}

// 递归调用，解析菜单数据Recursion
func (m *MenuService) RecursionCrt(menus []models.Menu) error {
	for _, menu := range menus {
		err := facades.Orm().Query().Model(&models.Menu{}).Create(&menu)
		if err != nil {
			return err
		}
		if menu.Children != nil {
			for i := 0; i < len(menu.Children); i++ {
				menu.Children[i].Pid = menu.ID
			}
			err := m.RecursionCrt(menu.Children)
			if err != nil {
				return err
			}

		}

	}
	return nil
}

func (m *MenuService) RecursionGet() ([]models.Menu, error) {
	menus := []models.Menu{}
	err := facades.Orm().Query().Model(&models.Menu{}).WhereNull("pid").With("Children").Find(&menus)
	if err != nil {
		return nil, err
	}
	for i := range menus {
		buildChildrenRecursively(&menus[i])
	}
	return menus, nil
}

func buildChildrenRecursively(parent *models.Menu) {
	children := []models.Menu{}
	err := facades.Orm().Query().Model(&models.Menu{}).Where("pid =?", parent.ID).Find(&children)
	if err != nil {
		return
	}
	// 在这里进行排序
	sort.Slice(children, func(i, j int) bool {
		return children[i].Meta.OrderNo < children[j].Meta.OrderNo
	})
	parent.Children = children
	for i := range children {
		buildChildrenRecursively(&children[i])
	}
}

func (m *MenuService) BuildPermissions() error {
	var count int64
	facades.Orm().Query().Model(&models.Permission{}).Count(&count)
	if count > 0 {
		return nil
	} else {
		facades.Orm().Query().Exec("TRUNCATE table permissions;")
		pers := []string{
			"system:role:list",
			"system:role:create",
			"system:role:read",
			"system:role:update",
			"system:role:delete",
			"system:menu:list",
			"system:menu:create",
			"system:menu:read",
			"system:menu:update",
			"system:menu:delete",
			"system:param-config:list",
			"system:param-config:create",
			"system:param-config:read",
			"system:param-config:update",
			"system:param-config:delete",
			"system:user:list",
			"system:user:create",
			"system:user:read",
			"system:user:update",
			"system:user:delete",
			"system:user:password:update",
			"system:user:pass:reset",
			"system:log:task:list",
			"system:log:login:list",
			"system:log:captcha:list",
			"app:health:network",
			"app:health:database",
			"app:health:memory-heap",
			"app:health:memory-rss",
			"app:health:disk",
			"netdisk:manage:list",
			"netdisk:manage:create",
			"netdisk:manage:info",
			"netdisk:manage:update",
			"netdisk:manage:delete",
			"netdisk:manage:mkdir",
			"netdisk:manage:token",
			"netdisk:manage:mark",
			"netdisk:manage:download",
			"netdisk:manage:rename",
			"netdisk:manage:cut",
			"netdisk:manage:copy",
			"system:dept:list",
			"system:dept:create",
			"system:dept:read",
			"system:dept:update",
			"system:dept:delete",
			"system:dict-item:list",
			"system:dict-item:create",
			"system:dict-item:read",
			"system:dict-item:update",
			"system:dict-item:delete",
			"system:dict-type:list",
			"system:dict-type:create",
			"system:dict-type:read",
			"system:dict-type:update",
			"system:dict-type:delete",
			"system:online:list",
			"system:online:kick",
			"system:task:list",
			"system:task:create",
			"system:task:read",
			"system:task:update",
			"system:task:delete",
			"system:task:once",
			"system:task:start",
			"system:task:stop",
			"todo:list",
			"todo:create",
			"todo:read",
			"todo:update",
			"todo:delete",
			"tool:storage:list",
			"tool:storage:delete",
			"upload:upload",
		}
		for _, per := range pers {
			err := facades.Orm().Query().Model(&models.Permission{}).Create(&models.Permission{
				Name: per,
			})
			if err != nil {
				return err
			}
		}
	}

	return nil
}
